﻿using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Resource;
using ArtMath.Setting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using ArtMath.CommonType;

namespace ArtMath.Component.Manager
{
    /// <summary>
    /// 切线管理器（自动）
    /// </summary>
    [Serializable]
    public class TangentLinesManager_A : TangentLinesManagerBase
    {
        [Browsable(false)]
        public Dictionary<TangentLine, double> NewSlopes { get; } = new Dictionary<TangentLine, double>();
        public TangentLinesManager_A(SketchPad pad, string name, LineBase cur, PointBase pt, bool addToList = true) : base(pad, name, cur, pt, addToList)
        {

        }
        public bool CheckLineNameExist(string name)
        {
            foreach (TangentLine item in Lines)
            {
                if (item.Name == name)
                {
                    return true;
                }
            }
            return false;
        }
        //public override void PointMove_Prepare(PointBase movePoint)
        //{
        //    foreach (TangentLine item in Lines)
        //    {
        //        item.Deformation_Prepare(item.TangentPoint);
        //    }
        //}
        //public override void PointMoved_Clean(PointBase movePoint)
        //{
        //    foreach (TangentLine item in Lines)
        //    {
        //        item.Deformation_Clean(item.TangentPoint);
        //    }
        //}
        public override void PointMoving_ManagedComponentsLimit(Base component)
        {
            NewSlopes.Clear();
            PointD[] tmp = curInfo.GetTangentPoints(PassPoint.NewXY);
            bool[] flag = new bool[Lines.Count];
            if (tmp != null)
            {
                for (int i = 0; i < tmp.Length; i++)
                {
                    PointD pxy = Pad.XYToPxy(tmp[i]);
                    double minDist = double.PositiveInfinity;
                    int minIndex = -1;
                    for (int j = 0; j < flag.Length; j++)
                    {
                        if (!flag[j])
                        {
                            double dist = pxy.DistanceTo(Lines[j].TangentPoint.Pxy);
                            if (dist < minDist)
                            {
                                minDist = dist;
                                minIndex = j;
                            }
                        }
                    }
                    if (minIndex < 0)
                    {
                        if (Settings.Instance.ManagerAutoAdd)
                        {
                            PointBase pt;
                            if (Pad.CoordinateType == CoordinateSystemType.PolarCoordinate)
                            {
                                pt = new PPoint_Fixed(Pad, $"{Resources.Translate("TangentPoint")}{i + 1}", false);
                            }
                            else
                            {
                                pt = new RPoint_Fixed(Pad, $"{Resources.Translate("TangentPoint")}{i + 1}", false);
                            }
                            pt.SpareCoordinate = pxy;
                            if (Pad.TryCreateObject(pt))
                            {
                                pt.OrderIndex = Pad.PointOrder++;
                                TangentLine line = new TangentLine(Pad, $"{Resources.Translate("TangentLine")}{i + 1}", Curve, this, false)
                                {
                                    Slope = tmp[i].GetSlope(PassPoint.NewXY),
                                    TangentPoint = pt,
                                };
                                if (Pad.TryCreateObject(line))
                                {
                                    Lines.Add(line);
                                }
                            }
                        }
                    }
                    else
                    {
                        Lines[minIndex].ObjectState = ObjectState.Normal;
                        NewSlopes.Add(Lines[minIndex], tmp[i].GetSlope(PassPoint.NewXY));
                        Lines[minIndex].TangentPoint.NewPxy = pxy;
                        flag[minIndex] = true;
                    }
                }
                foreach (TangentLine item in NewSlopes.Keys)
                {
                    item.TangentPoint.Move(item.TangentPoint.NewPxy, true);
                }
            }
            for (int i = flag.Length - 1; i >= 0; i--)
            {
                if (!flag[i])
                {
                    if (Settings.Instance.ManagerAutoDelete && Lines[i].IsIndependent)
                    {
                        Lines[i].Delete();
                        Lines.RemoveAt(i);
                    }
                    else
                    {
                        Lines[i].ObjectState = ObjectState.Deleted;
                    }
                }
            }
        }
        //public override Base[] CheckNearBy(PointD Plocation)
        //{
        //    HashSet<Base> objs = new HashSet<Base>(base.CheckNearBy(Plocation));
        //    //foreach (TangentLine item in Lines)
        //    //{
        //    //    objs.AddRange(item.CheckNearBy(Plocation));
        //    //}
        //    if (PassPoint.LayerItem == null)
        //    {
        //        objs.AddRange(PassPoint.CheckNearBy(Plocation));
        //    }
        //    return objs.ToArray();
        //}
        public override void InChildrenIterator(Predicate<ShapeBase> act)
        {
            base.InChildrenIterator(act);
            if (act == null) return;
            act(PassPoint);
        }
        public override void CreateComponents()
        {
            if (PassPoint == null)
            {
                PassPoint = Pad.CreatePoint(Resources.Translate("PassPoint"), SpareCoordinate_);
                Name = Pad.StdObjName("TangentLine");
            }
            PointD[] tmp = curInfo.GetTangentPoints(PassPoint.ToPointD());
            if (tmp != null)
            {
                TangentLine line;
                PointD pxy;
                PointBase pt;
                for (int i = 0; i < tmp.Length; i++)
                {
                    pxy = Pad.XYToPxy(tmp[i]);
                    if (Pad.CoordinateType == CoordinateSystemType.PolarCoordinate)
                    {
                        pt = new PPoint_Fixed(Pad, $"{Resources.Translate("TangentPoint")}{i + 1}", false);
                    }
                    else
                    {
                        pt = new RPoint_Fixed(Pad, $"{Resources.Translate("TangentPoint")}{i + 1}", false);
                    }
                    pt.SpareCoordinate = pxy;
                    if (Pad.TryCreateObject(pt))
                    {
                        pt.OrderIndex = Pad.PointOrder++;
                        line = new TangentLine(Pad, $"{Resources.Translate("TangentLine")}{i + 1}", Curve, this, false)
                        {
                            Slope = tmp[i].GetSlope(PassPoint.ToPointD()),
                            TangentPoint = pt,
                        };
                        if (Pad.TryCreateObject(line))
                        {
                            //line.SetPoint(1, PassPoint);
                            Lines.Add(line);
                        }
                    }
                }
            }
            base.CreateComponents();
            if (PassPoint.LayerItem != null)
            {
                PassPoint.LayerItem.Swap(LayerItem.Index);
            }
        }
    }
}
